package com.ititer.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import com.ititer.AbstractBean;
import com.ititer.bean.AccountBean;
import com.ititer.bean.CompetenceBean;
import com.ititer.dao.AccountDao;
import com.ititer.dao.AccountDomainsDao;
import com.ititer.dao.CompetenceDao;
import com.ititer.dao.IpsDao;
import com.ititer.dao.LoginLogDao;
import com.ititer.dao.ProfileDao;
import com.ititer.dao.RegisterLogDao;
import com.ititer.enums.AccountStatus;
import com.ititer.enums.LoginState;
import com.ititer.mail.MailSender;
import com.ititer.model.Account;
import com.ititer.model.AccountDomains;
import com.ititer.model.Competence;
import com.ititer.model.LoginLog;
import com.ititer.model.Profile;
import com.ititer.model.RegisterLog;
import com.ititer.result.LoginResult;
import com.ititer.service.AbstractService;
import com.ititer.service.AccountService;

@Component
public class AccountServiceImpl extends AbstractService implements AccountService {

	@Autowired
	private AccountDao accountDao;

	@Autowired
	private RegisterLogDao registLogDao;

	@Autowired
	private LoginLogDao loginLogDao;

	@Autowired
	private CompetenceDao competenceDao;

	@Autowired
	private IpsDao ipsDao;

	@Autowired
	private AccountDomainsDao domainsDao;

	@Autowired
	private ProfileDao profileDao;

	@Autowired
	private MailSender sender;

	@Override
	public boolean register(AccountBean registerData) {
		//save account
		Account account = registerData.bindTo(Account.class);
		int accountSaved = accountDao.create(account);

		//save register log
		RegisterLog registerLog = new RegisterLog();
		registerData.bindTo(registerLog);
		registerLog.setAccountId(account.getId());
		registerLog.setRegisterTime(account.getCreateTime());
		registerLog.setReferer(registerData.getReferer());
		registLogDao.create(registerLog);

		//TODO send email.
		sender.sendRegisterMail(account.getEmail(), account.getPasswd(), "http://www.ititer.com/login");
		return accountSaved == 1;
	}

	@Override
	public boolean isEmailExist(String email) {
		return accountDao.isEmailExist(email);
	}

	@Override
	public LoginResult login(AccountBean loginData) {
		LoginResult result = newLoginResult();
		String email = loginData.getEmail();
		Account account = accountDao.getAccount(email, loginData.getPasswd());

		if (null == account) {
			if (isEmailExist(email)) {
				result.setState(LoginState.PasswordError);
			} else {
				result.setState(LoginState.AccountNotExist);
			}
		} else {
			//update status for the first time login,update last login time...
			String status = account.getStatus();
			if (AccountStatus.Registering.name().equals(status)) {
				account.setStatus(AccountStatus.Actived.name());
			}
			account.setLastLoginTime(loginData.getLastLoginTime());
			accountDao.update(account);
			//save login log
			saveLoginLog(loginData, account);

			result.setState(LoginState.Success);
			result.setAccount(account);
		}
		return result;
	}

	@Override
	public boolean isUriExist(String domain) {
		return accountDao.isUriExist(domain);
	}

	@Override
	public boolean updateUri(AccountBean accountBean) {
		Account account = accountBean.bindTo(Account.class);
		int updated = accountDao.update(account);
		return updated == 1;
	}

	@Override
	public Account getByUri(String domain) {
		return accountDao.getByUri(domain);
	}

	@Override
	public boolean saveCompetence(CompetenceBean competenceBean) {
		Competence competence = competenceDao.getCompetence(competenceBean.getAccountId(), competenceBean.getItem());

		Competence entity = competenceBean.bindTo(Competence.class);
		int updateRow = 0;
		if (competence == null) {
			updateRow = competenceDao.create(entity);
		} else {
			entity.setId(competence.getId());
			updateRow = competenceDao.update(entity);
		}
		return updateRow == 1 ? true : false;
	}

	@Override
	public List<CompetenceBean> listCompetence(Integer userid) {
		List<Competence> competences = competenceDao.getCompetences(userid);
		if (CollectionUtils.isEmpty(competences)) {
			return null;
		}
		List<CompetenceBean> result = new ArrayList<CompetenceBean>();
		if (!CollectionUtils.isEmpty(competences)) {
			for (Competence competence : competences) {
				CompetenceBean cb = new CompetenceBean();
				cb.bindFrom(competence);
				result.add(cb);
			}
		}
		return result;
	}

	public void setSender(MailSender sender) {
		this.sender = sender;
	}

	private LoginResult newLoginResult() {
		LoginResult result = new LoginResult();
		return result;
	}

	private void saveLoginLog(AccountBean loginData, Account account) {
		LoginLog loginLog = new LoginLog();
		loginLog.setAccountId(account.getId());
		loginLog.setIp(loginData.getIp());
		loginLog.setLoginTime(account.getLastLoginTime());
		loginLog.setReferer(loginData.getReferer());
		loginLogDao.create(loginLog);
	}

	@Override
	public int getLoginCount(Integer accountid) {
		return loginLogDao.count(accountid);
	}

	@Override
	//TODO : use batch to enhance the performance.
	public boolean updateDomain(AccountBean account) {
		if (ArrayUtils.isEmpty(account.getDomains())) {
			return true;
		}
		Integer id = account.getId();
		domainsDao.deleteByAccount(id);

		for (String domain : account.getDomains()) {
			AccountDomains ad = new AccountDomains();
			ad.setAccountId(id);
			ad.setDomain(domain);
			domainsDao.create(ad);
		}
		return true;
	}

	@Override
	public List<AccountDomains> getDomains(Integer accountid) {
		return domainsDao.getDomains(accountid);
	}

	@Override
	public Profile getProfile(Integer id) {
		return profileDao.getById(id);
	}

	@Override
	public boolean updateProfile(AbstractBean bean, Integer accountId) {
		Profile profile = profileDao.getById(accountId);
		boolean isNew = false;
		if (profile == null) {
			profile = new Profile();
			isNew = true;
		}
		bean.bindTo(profile);
		profile.setAccountId(accountId);
		if (!isNew) {
			return profileDao.update(profile);
		} else {
			return profileDao.insert(profile);
		}
	}
}
